package com.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.dao.QuestionActionDAO;
import com.dao.QuestionCommentDAO;
import com.dao.QuestionDAO;
import com.dao.TagDAO;
import com.dao.TimelineDAO;
import com.dao.UserDAO;
import com.model.Question;
import com.model.QuestionAction;
import com.model.QuestionComment;
import com.model.Tag;
import com.model.Timeline;
import com.model.User;
import com.service.QuestionService;
import com.util.Page;

@Service
public class QuestionServiceImpl implements QuestionService {
	@Autowired
	private UserDAO userDAO;

	@Autowired
	private TagDAO tagDAO;

	@Autowired
	private QuestionDAO questionDAO;

	@Autowired
	private QuestionActionDAO questionActionDAO;

	@Autowired
	private QuestionCommentDAO questionCommentDAO;

	@Autowired
	private TimelineDAO timelineDAO;

	@Transactional
	public Question addQuestion(int uid, int quid, String question, int qscore, int isPublic, int isAnonymous) {
		try {
			Question q = new Question();
			User user = new User();
			user.setId(uid);
			User quser = new User();
			quser.setId(quid);
			q.setUserByUserId(user);
			q.setUserByQuestionUserId(quser);
			q.setQuestion(question);
			q.setQuestionAt(new Date());
			q.setAgreeNum(0);
			q.setDisagreeNum(0);
			q.setFavorNum(0);
			q.setUserScore(qscore);
			q.setIsAnswered(0);
			q.setIsElite(0);
			q.setIsIgnore(0);
			q.setIsPublic(isPublic);
			q.setIsAnonymous(isAnonymous);
			questionDAO.add(q);
			Timeline t = new Timeline(user, "question", q.getId(), new Date());
			t.setIsPublic(isPublic);
			timelineDAO.addEvent(t);
			userDAO.addQuestionsNum(uid);
			return q;
		}
		catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return null;
	}

	@Transactional
	public int deleteQuestion(int id) {
		questionDAO.delete(id);
		return id;
	}

	@Transactional
	public Question answerQuestion(int id, String answer, int answerUserId) {
		try {
			Question q = questionDAO.findById(id);
			int uid = q.getUserByUserId().getId();
			if (uid != answerUserId) {
				return null;
			}
			q.setAnswer(answer);
			q.setIsAnswered(1);
			q.setAnswerAt(new Date());
			q.setIsIgnore(0);
			questionDAO.update(q);

			int qscore = q.getUserScore();

			int quid = q.getUserByQuestionUserId().getId();
			userDAO.addScore(uid, qscore);
			userDAO.reduceScore(quid, qscore);
			userDAO.addAnswersNum(uid);
			userDAO.reduceQuestionsNum(uid);

			User user = new User();
			user.setId(uid);
			Timeline t = new Timeline(user, "answer", id, new Date());
			t.setIsPublic(q.getIsPublic());
			timelineDAO.addEvent(t);
			return q;
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Transactional
	public int addQuestionTag(int qid, String tagName) {

		List<Tag> taglist = tagDAO.findByName(tagName);
		if (taglist.size() > 0) {
			Tag tag = taglist.get(0);
			if (!questionDAO.isTagExist(tag.getId(), qid)) {
				questionDAO.addQuestionTag(tag.getId(), qid);
			}
		}
		else {
			Tag tag = new Tag();
			tag.setName(tagName);
			tag.setDescription(tagName);
			tagDAO.addTag(tag);
			questionDAO.addQuestionTag(tag.getId(), qid);
		}
		return qid;
	}

	@Transactional
	public String agreeQuestion(int qid, int uid) {
		if (questionActionDAO.isExist(qid, uid, "agree")) {
			return "exist";
		}
		else {
			QuestionAction qa = new QuestionAction();
			User u = new User();
			u.setId(uid);
			Question q = new Question();
			q.setId(qid);

			qa.setUser(u);
			qa.setQuestion(q);
			qa.setActionType("agree");
			qa.setCreateAt(new Date());
			questionActionDAO.add(qa);
			questionDAO.agree(qid);
			return "success";
		}
	}

	@Transactional
	public String disagreeQuestion(int qid, int uid) {
		if (questionActionDAO.isExist(qid, uid, "disagree")) {
			return "exist";
		}
		else {
			QuestionAction qa = new QuestionAction();
			User u = new User();
			u.setId(uid);
			Question q = new Question();
			q.setId(qid);

			qa.setUser(u);
			qa.setQuestion(q);
			qa.setActionType("disagree");
			qa.setCreateAt(new Date());
			questionActionDAO.add(qa);
			questionDAO.disagree(qid);
			return "success";
		}
	}

	@Transactional
	public String favorQuestion(int qid, int uid) {
		if (questionActionDAO.isExist(qid, uid, "favor")) {
			return "exist";
		}
		else {
			QuestionAction qa = new QuestionAction();
			User u = new User();
			u.setId(uid);
			Question q = new Question();
			q.setId(qid);

			qa.setUser(u);
			qa.setQuestion(q);
			qa.setActionType("favor");
			qa.setCreateAt(new Date());
			questionActionDAO.add(qa);
			questionDAO.favor(qid);
			return "success";
		}
	}

	@Transactional
	public String collectQuestion(int qid, int uid) {
		if (questionActionDAO.isExist(qid, uid, "collect")) {
			return "exist";
		}
		else {
			QuestionAction qa = new QuestionAction();
			User u = new User();
			u.setId(uid);
			Question q = new Question();
			q.setId(qid);

			qa.setUser(u);
			qa.setQuestion(q);
			qa.setActionType("collect");
			qa.setCreateAt(new Date());
			questionActionDAO.add(qa);
			questionDAO.collect(qid);
			return "success";
		}
	}

	@Transactional
	public void addComment(int qid, int uid, String comment) {
		try {
			Question q = new Question();
			q.setId(qid);
			User u = new User();
			u.setId(uid);

			QuestionComment c = new QuestionComment();
			c.setQuestion(q);
			c.setUser(u);
			c.setContents(comment);
			c.setCreateAt(new Date());
			c.setAgreeNum(0);
			c.setDisagreeNum(0);
			questionCommentDAO.add(c);
			questionDAO.addCommentNum(qid);
		}
		catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	@Transactional
	public void agreeComment(int id) {
		questionCommentDAO.addAgree(id);
	}

	@Transactional
	public void disagreeComment(int id) {
		questionCommentDAO.addDisagree(id);
	}

	@Transactional
	public Question findById(int id) {
		return questionDAO.findById(id);
	}

	@Transactional
	public Page getAnswerdQuestionByPage(int id, int page, int pageSize) {
		return questionDAO.findAnsweredByPage(id, page, pageSize);
	}
	
	@Transactional
	public Page getAnswerdQuestionByPage(int id, int page, int pageSize, boolean isPublic) {
		return questionDAO.findAnsweredByPagePublic(id, page, pageSize);
	}

	@Transactional
	public Page getUnAnswerdQuestionByPage(int userId, int page, int pageSize) {
		return questionDAO.findUnAnsweredByPage(userId, page, pageSize);
	}
	
	@Transactional
	public Page getIgnoredQuestion(int userId, int page, int pageSize) {
		return questionDAO.findIgnoreByPage(userId, page, pageSize);
	}
	
	@Transactional
	public Page findSendQuestionByPage_All(int userId, int page, int pageSize){
		return questionDAO.findSendQuestionByPage_All(userId, page, pageSize);
	}
	
	@Transactional
	public Page findSendQuestionByPage_AnswerdAll(int userId, int page, int pageSize) {
		return questionDAO.findSendQuestionByPage_AnswerdAll(userId, page, pageSize);
	}
	
	@Transactional
	public Page findSendQuestionByPage_AnswerdPublic(int userId, int page, int pageSize) {
		return questionDAO.findSendQuestionByPage_AnswerdPublic(userId,page,pageSize);
	}
	
	@Transactional
	public Page findSendQuestionByPage_UnAsnwerd(int userId, int page, int pageSize) {
		return questionDAO.findSendQuestionByPage_UnAsnwerd(userId, page, pageSize);
	}
	
	@Transactional
	public Page findSendQuestionByPage_Ignored(int userId, int page, int pageSize) {
		return questionDAO.findSendQuestionByPage_Ignored(userId, page, pageSize);
	}

	
	@Transactional
	public boolean ignoreQuestion(int questionId, int userId) {
		Question question = questionDAO.findById(questionId);
		if(question.getUserByUserId().getId()!=userId){
			return false;
		}
		userDAO.reduceQuestionsNum(userId);
		questionDAO.ignore(questionId);
		return true;
	}
	
	@Transactional
	public boolean unignoreQuestion(int questionId, int userId) {
		Question question = questionDAO.findById(questionId);
		if(question.getUserByUserId().getId()!=userId){
			return false;
		}
		userDAO.addQuestionsNum(userId);
		questionDAO.unIgnore(questionId);
		return true;
	}
	
	@Transactional
	public List findCommentsByPage(int questionId, int page, int pageSize){
		return questionCommentDAO.findByPage(questionId, page, pageSize);
	}

	@Transactional
	public List<Tag> findQuestionTags(int questionId) {
		// TODO Auto-generated method stub
		return questionDAO.findTagsByQuestionId(questionId);
	}

	@Transactional
	public Map findByIdWithUser(int questionId) {
		// TODO Auto-generated method stub
		return questionDAO.findQuestionByIdWithUser(questionId);
	}

	@Transactional
	public void doCommentAction(int targetId, String action) {
		// TODO Auto-generated method stub
		if(action.equals("agree")){
			questionCommentDAO.addAgree(targetId);
		}else if(action.equals("disagree")){
			questionCommentDAO.addDisagree(targetId);
		}
	}
	@Transactional
	public List findNewQuestionTopN(int topN) {
		// TODO Auto-generated method stub
		return questionDAO.findNewQuestionTopN(topN);
	}
	@Transactional
	public List findHotQuestionTopN(int topN) {
		// TODO Auto-generated method stub
		return questionDAO.findHotQuestionTopN(topN);
	}
	
	
}
